home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
doom
/
suckmods.zip
/
SUCK05
/
SRC
/
COMBAT.QC
< prev
next >
Wrap
Text File
|
1997-05-13
|
16KB
|
690 lines
void() T_MissileTouch;
void() info_player_start;
void(entity targ, entity attacker) ClientObituary;
//============================================================================
/*
============
CanDamage
Returns true if the inflictor can directly damage the target. Used for
explosions and melee attacks.
============
*/
float(entity targ, entity inflictor) CanDamage =
{
// bmodels need special checking because their origin is 0,0,0
if (targ.movetype == MOVETYPE_PUSH)
{
traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
if (trace_fraction == 1)
return TRUE;
if (trace_ent == targ)
return TRUE;
return FALSE;
}
traceline(inflictor.origin, targ.origin, TRUE, self);
if (trace_fraction == 1)
return TRUE;
traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
if (trace_fraction == 1)
return TRUE;
traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
if (trace_fraction == 1)
return TRUE;
traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
if (trace_fraction == 1)
return TRUE;
traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
if (trace_fraction == 1)
return TRUE;
return FALSE;
};
/*
============
Killed
============
*/
void(entity targ, entity attacker) Killed =
{
local entity oself, tempe, onew, oother;
oself = self;
self = targ;
if (self.health < -99)
self.health = -99; // don't let sbar look bad if a player
if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
{ // doors, triggers, etc
self.th_die ();
self = oself;
return;
}
if ((targ.health > -40) && (targ.rune_num == ITEM_RUNE_ANKH) && (random() < 0.9))
{
targ.msg_center = 1;
clientmsg(targ, "The power of the Ankh has resurrected you!\n");
targ.health = targ.health + 40;
self=oself;
return;
}
if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
(targ.team == targ.lastteam))
{
tempe=spawn();
tempe.ammo_rockets=self.ammo_rockets;
tempe.ammo_shells=self.ammo_shells;
tempe.ammo_nails=self.ammo_nails;
tempe.ammo_cells=self.ammo_cells;
tempe.items=self.items;
tempe.owner = targ;
tempe.items = 0;
onew=self;
oother = other;
self=tempe;
other=attacker;
BackpackTouch();
other=oother;
self=onew;
self.ammo_rockets=0;
self.ammo_shells=0;
self.ammo_nails=0;
self.ammo_cells=0;
self.items=0;
}
self.enemy = attacker;
ClientObituary(self, attacker);
self.takedamage = DAMAGE_NO;
self.touch = SUB_Null;
self.th_die ();
self = oself;
};
// *TEAMPLAY*
// Prototypes
float(entity targ, entity inflictor, entity attacker, float damage) TeamArmorDam;
float(entity targ, entity inflictor, entity attacker, float damage) TeamHealthDam;
/*
============
T_Damage
The damage is coming from inflictor, but get mad at attacker
This should be the only function that ever reduces health.
============
*/
void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
{
local vector dir;
local entity oldself;
local float save;
local float take;
local string tmp_string;
local float tmp_float, tmp2;
local entity e;
local float attacker_tmts, targ_tmts, modifier;
if (!targ.takedamage)
return;
if ((targ.rune_num == ITEM_RUNE_LOKI) && (targ.loki_possessed) &&
(!(targ.player_flag&ITEM_ENEMY_FLAG)))
return;
if (targ.stone_time > time)
return;
//SUCK: Figure the momentum change first
if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) &&
(targ.rune_num != ITEM_RUNE_MONK))
{
dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
dir = normalize(dir);
if ((attacker.rune_num == ITEM_RUNE_SAMURAI) &&
((attacker.weapon == IT_ROCKET_LAUNCHER) ||
(attacker.weapon == IT_GRENADE_LAUNCHER)))
targ.velocity = targ.velocity + dir * damage * 32;
else
targ.velocity = targ.velocity + dir*damage*8;
}
// Ifrite does no damage to himself.
if ((attacker == targ) && (attacker.rune_num == ITEM_RUNE_IFRITE))
return;
// Mars does less damage to himself...
if ((targ == attacker) && (attacker.rune_num == ITEM_RUNE_MARS))
damage = damage / 5;
if (attacker.rune_num == ITEM_RUNE_MARS)
damage=damage*3;
// Golom takes 1/4 damage..
if (targ.rune_num == ITEM_RUNE_GOLOM)
damage = damage / 4;
// Kizi does more damage the lower his health.
if (attacker.rune_num == ITEM_RUNE_KIZI)
{
if (attacker.health <= 40)
damage = damage * 3;
else if (attacker.health < 70)
damage = damage * 2;
else if (attacker.health < 85)
damage = damage * 1.5;
}
// Kizi takes less damage the lower his health.
if (targ.rune_num == ITEM_RUNE_KIZI)
{
if (targ.health <= 40)
damage = damage / 3;
else if (attacker.health < 70)
damage = damage / 2;
else if (attacker.health < 85)
damage = damage / 1.5;
}
// Sargon does double damage to the judaic set
if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
((targ.rune_num == ITEM_RUNE_GOLOM) ||
(targ.rune_num == ITEM_RUNE_SHYLOCK) ||
(targ.rune_num == ITEM_RUNE_SAMPSON) ||
(targ.rune_num == ITEM_RUNE_DAVID)))
damage = damage * 2;
// Sargon does extra damage to the flag carrier.
else if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
(targ.player_flag&ITEM_ENEMY_FLAG))
damage = damage * 2;
// Mars takes 1.8x damage.
if (targ.rune_num == ITEM_RUNE_MARS)
damage=damage*1.8;
if ((attacker.rune_num == ITEM_RUNE_WITCH) &&
(targ.classname == "player") &&
(targ.curse_time == 0) && (random() < 0.8) &&
(targ.team != attacker.team))
{
targ.msg_center = 1;
clientmsg(targ, "You have been cursed!\n");
targ.curse_time = time + 7;
}
if ((targ.rune_num == ITEM_RUNE_MONK) && (vlen(targ.velocity) < 30) && ((targ.player_flag&ITEM_ENEMY_FLAG) == 0)
&& ((targ.attack_finished + 3) < time))
return;
// The vampire gains some of the health he takes from enemies.
if ((attacker.rune_num == ITEM_RUNE_VAMPIRE) &&
(attacker.team != targ.team) &&
(targ.classname == "player"))
{
if (attacker.health<170)
{
tmp_float = damage/3;
attacker.health=attacker.health + tmp_float;
if (attacker.health>200)
attacker.health = 200;
}
}
/* If Ytr is nearby and on the enemy team and we are the attacker,
decrease our strength. */
e=findradius(attacker.origin, 600);
while (e)
{
if ((e.rune_num == ITEM_RUNE_YTR) &&
(e.team != attacker.team))
damage = damage / 2;
e=e.chain;
}
// Wendigo locks in the velocity of the enemy.
if ((attacker.rune_num == ITEM_RUNE_WENDIGO) && (targ!=attacker)
&& (targ.team != attacker.team))
{
targ.lock_velocity=targ.velocity;
targ.lock_time=time+1.5;
}
// used by buttons and triggers to set activator for target firing
damage_attacker = attacker;
//SUCK: Increase damage of attacker by 10% for every teammate close to him
// and increase resistance of target by 10% for every teammate close to him.
if (teamplay&TEAM_GROUP_POWER)
{
attacker_tmts=0;
e=findradius(attacker.origin, 300);
while (e)
{
if (e.classname == "player")
{
if (e.team == attacker.team)
attacker_tmts=attacker_tmts + 1;
}
e=e.chain;
}
tmp_string=ftos(attacker_tmts);
targ_tmts=0;
e=findradius(targ.origin, 300);
while (e)
{
if (e.classname == "player")
{
if (e.team == targ.team)
targ_tmts=targ_tmts + 1;
}
e=e.chain;
}
tmp_string=ftos(targ_tmts);
while(attacker_tmts>0)
{
damage=damage*1.1;
attacker_tmts=attacker_tmts - 1;
}
while (targ_tmts>0)
{
damage=damage*0.9;
targ_tmts=targ_tmts - 1;
}
}
// SUCK: If the player has the rune of castle, then his resistance and damage
// increase when he is near his flag
if (attacker.rune_num == ITEM_RUNE_CASTLE)
{
attacker_tmts=0;
e=findradius(attacker.origin, 800);
while (e)
{
if (((e.classname == "item_flag_team1") && (attacker.team == (TEAM_COLOR1 + 1))) ||
((e.classname == "item_flag_team2") && (attacker.team == (TEAM_COLOR2 + 1))))
attacker_tmts=1;
e=e.chain;
}
if (attacker_tmts == 1)
{
if (attacker.super_sound< time)
{
sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
attacker.super_sound = time + 1;
}
damage = damage * 3;
}
else
damage = damage * 0.9;
}
if (targ.rune_num == ITEM_RUNE_CASTLE)
{
targ_tmts = 0;
e=findradius(targ.origin, 800);
while (e)
{
if (((e.classname == "item_flag_team1") && (targ.team == (TEAM_COLOR1 + 1))) ||
((e.classname == "item_flag_team2") && (targ.team == (TEAM_COLOR2 + 1))))
targ_tmts=1;
e=e.chain;
}
if (targ_tmts == 1)
damage = damage / 3;
else
damage = damage * 1.3;
}
// SUCK: If he has the rune of siege, then he becomes more powerful
// near the ENEMY flag or if he has it.
if ((attacker.rune_num == ITEM_RUNE_SIEGE) &&
(attacker.player_flag&ITEM_ENEMY_FLAG))
{
damage = damage * 2;
if (attacker.super_sound< time)
{
sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
attacker.super_sound = time + 1;
}
}
else if (attacker.rune_num == ITEM_RUNE_SIEGE)
{
attacker_tmts=0;
e=findradius(attacker.origin, 800);
while (e)
{
if (((e.classname == "item_flag_team1") && (attacker.team == (TEAM_COLOR2 + 1))) ||
((e.classname == "item_flag_team2") && (attacker.team == (TEAM_COLOR1 + 1))))
attacker_tmts=1;
e=e.chain;
}
if (attacker_tmts == 1)
{
damage = damage * 2;
if (attacker.super_sound< time)
{
sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
attacker.super_sound = time + 1;
}
}
}
if ((targ.rune_num == ITEM_RUNE_SIEGE) &&
(targ.player_flag & ITEM_ENEMY_FLAG))
{
damage = damage / 2;
if (targ.invincible_sound < time)
{
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
targ.invincible_sound = time + 2;
}
}
else if (targ.rune_num == ITEM_RUNE_SIEGE)
{
targ_tmts=0;
e=findradius(targ.origin, 800);
while (e)
{
if (((e.classname == "item_flag_team1") && (targ.team == (TEAM_COLOR2 + 1))) ||
((e.classname == "item_flag_team2") && (targ.team == (TEAM_COLOR1 + 1))))
targ_tmts=1;
e=e.chain;
}
if (targ_tmts == 1)
{
damage = damage / 2;
if (targ.invincible_sound < time) {
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
targ.invincible_sound = time + 2;
}
}
else
damage = damage;
}
// check for quad damage powerup on the attacker
if ((attacker.super_damage_finished > time) &&
(attacker.rune_num != ITEM_RUNE_MARS))
damage = damage * 4;
// RUNE: check for double damage for rune of Black Magic powerup
if (attacker.rune_num == ITEM_RUNE_DBLDMG)
damage = damage * 2;
if ((attacker.rune_num == ITEM_RUNE_VAMPIRE) ||
(attacker.rune_num == ITEM_RUNE_VIKING))
damage = damage * 1.3;
if ((targ.rune_num == ITEM_RUNE_ARTHUR) &&
(attacker.classname == "player"))
damage = damage / 2;
if ((targ.rune_num == ITEM_RUNE_VIKING) &&
(attacker.rune_num == ITEM_RUNE_ARTHUR))
damage = damage * 2.5;
if ((attacker.rune_num == ITEM_RUNE_BALDER) &&
(targ.team != attacker.team))
{
targ.balder_slowdown = targ.balder_slowdown + 1;
targ.balder_time = time + 1;
}
// The viking badly damages the priest
if ((attacker.rune_num == ITEM_RUNE_VIKING) &&
(targ.rune_num == ITEM_RUNE_PRIEST))
damage = damage * 2.5;
// save damage based on the target's armor level
// *TEAMPLAY*
// TeamArmorDam returns true iff the attacker can damage the target's
// armor
if (TeamArmorDam(targ, inflictor, attacker, damage))
save = ceil(targ.armortype*damage);
else
save = 0;
// SUCK: The werewolf doesn't lose armor
if (targ.rune_num == ITEM_RUNE_WEREWOLF)
save=0;
if (attacker.rune_num == ITEM_RUNE_SHOGUN)
save = save * 2;
if (save >= targ.armorvalue)
{
save = targ.armorvalue;
targ.armortype = 0; // lost all armor
targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
}
if (attacker.rune_num == ITEM_RUNE_SHOGUN)
save = save / 2;
take = ceil(damage-save);
// Vulcan has tough skin.
if (targ.rune_num == ITEM_RUNE_VULCAN)
take = take / 2;
//RUNE check if target has rune of Earth Magic (half damage)
if (targ.rune_num == ITEM_RUNE_RESIST) {
take = take / 2;
save = save / 2;
if (targ.invincible_sound < time) {
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
targ.invincible_sound = time + 2;
}
}
// Reduce his armor.
targ.armorvalue = targ.armorvalue - save;
if ((targ.rune_num == ITEM_RUNE_SHYLOCK) &&
(targ != attacker) && (attacker.classname == "player"))
{
attacker.deathweapon="shylock";
T_Damage(attacker, targ, targ, damage);
attacker.deathweapon="";
}
//SUCK: Vampires take 0.8x damage.
if (targ.rune_num == ITEM_RUNE_VAMPIRE)
{
take = take * 0.8;
if (targ.rune_sound_start < time)
{
sound(targ, CHAN_VOICE, "wizard/widle2.wav", 1, ATTN_NORM);
targ.rune_sound_start = time + 2.5;
}
}
// add to the damage total for clients, which will be sent as a single
// message at the end of the frame
// FIXME: remove after combining shotgun blasts?
if (targ.flags & FL_CLIENT)
{
targ.dmg_take = targ.dmg_take + take;
targ.dmg_save = targ.dmg_save + save;
targ.dmg_inflictor = inflictor;
}
if (targ.invincible_finished >= time)
{
if (self.invincible_sound < time)
{
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
self.invincible_sound = time + 2;
}
return;
}
// team play damage avoidance
if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
return;
// *TEAMPLAY*
// TeamHealthDam will return true if the attacker can damage the target's
// health
// do the damage
targ.health = targ.health - take;
if (!TeamHealthDam(targ, inflictor, attacker, damage))
targ.health = targ.health + take;
if (!TeamHealthDam(targ, inflictor, attacker, damage))
return;
if (targ.health <= 0)
{
Killed (targ, attacker);
return;
}
// react to the damage
oldself = self;
self = targ;
if (self.th_pain)
{
self.th_pain (attacker, take);
}
self = oldself;
};
/*
============
T_RadiusDamage
============
*/
void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
{
local float points;
local entity head;
local vector org;
if (attacker.rune_num == ITEM_RUNE_IFRITE)
head = findradius(inflictor.origin, (damage+40)*1.4);
else
head = findradius(inflictor.origin, damage+40);
while (head)
{
if (head != ignore)
{
if (head.takedamage)
{
org = head.origin + (head.mins + head.maxs)*0.5;
points = 0.5*vlen (inflictor.origin - org);
if (points < 0)
points = 0;
points = damage - points;
if (head == attacker)
points = points * 0.5;
if ((points > 0) && CanDamage(head, inflictor) &&
((head.rune_num != ITEM_RUNE_MONK) || (attacker == head)))
T_Damage (head, inflictor, attacker, points);
}
}
head = head.chain;
}
};
/*
============
T_DischargeDamage
============
*/
void(entity inflictor, entity attacker, float damage, entity ignore) T_DischargeDamage =
{
local float points;
local entity head;
local vector org;
head = findradius(inflictor.origin, damage+40);
while (head)
{
if (head != ignore)
{
if (head.takedamage)
{
org = head.origin + (head.mins + head.maxs)*0.5;
points = 0.5*vlen (inflictor.origin - org);
if (points < 0)
points = 0;
points = damage - points;
if (head == attacker)
points = points * 0.5;
if (points > 0)
{
if (CanDamage (head, inflictor))
if (head.waterlevel > 1)
T_Damage (head, inflictor, attacker, points);
}
}
}
head = head.chain;
}
};
/*
============
T_BeamDamage
============
*/
void(entity attacker, float damage) T_BeamDamage =
{
local float points;
local entity head;
head = findradius(attacker.origin, damage+40);
while (head)
{
if (head.takedamage)
{
points = 0.5*vlen (attacker.origin - head.origin);
if (points < 0)
points = 0;
points = damage - points;
if (head == attacker)
points = points * 0.5;
if ((points > 0) && CanDamage(head, attacker))
T_Damage (head, attacker, attacker, points);
}
head = head.chain;
}
};